<?php

class CriarObjetoDAO {

    /**
     * Enter description here...
     *
     * @param Tabela $objTabela
     * @return String
     */
    public static function execute($objTabela) {
        $t = '    ';
        $matInteiros = array('tinyint', 'smallint', 'mediumint', 'int', 'integer', 'bigint', 'float', 'double', 'double precision', 'real', 'numeric');

        /* Primeiro caracter em maiusculo, como manda a convencao. */
        $tabela = Util::nomeDbToClasse(strtolower($objTabela->getNomeTabela()));

        /* Iniciando a criacao do conteudo do arquivo */
        $conteudo = '<?php' . "\n";
        $conteudo .= "$t" . 'require_once ROOT . \'server/classes/arquitetura/dao/AbstractDao.class.php\';' . "\n";
        $conteudo .= "\n$t" . 'class ' . $tabela . "Dao extends AbstractDao {\n";

        $conteudo .= "\n$t    const TABLE_NAME = '" . $objTabela->getNomeTabela() . "';\n";

        //Attibute $entity
        $conteudo .= "\n$t$t" . 'private $entity;' . "\n\n";

        for ($i = 0; $i < count($objTabela->getCampos()); $i++) {
            if ($objTabela->getExtra($i) != 'auto_increment') {
                if ($objTabela->getCampo($i) != 'insert_date' && $objTabela->getCampo($i) != 'update_date' && $objTabela->getCampo($i) != 'ativo') {
                    $conteudo .= "$t    private $" . Util::nomeDbToAtributo($objTabela->getCampo($i)) . ";\n";
                }
            }
        }

        //Constructor
        $conteudo .= "\n$t$t" . '/**' . "\n$t$t * Construtor padrao.\n$t$t */\n$t$t" . 'public function __construct($entity) {' . "\n";
        $conteudo .= "$t$t$t" . 'parent::__construct();' . "\n";
        $conteudo .= "$t$t$t" . '$this->setEntity($entity);' . "\n";
        $conteudo .= "$t$t}\n";

        //Method setEntity
        $conteudo .= "\n$t$t" . 'public function setEntity($entity) {' . "\n";
        $conteudo .= "$t$t$t" . '$this->entity = $entity;' . "\n";
        $conteudo .= "$t    }\n";

        //Method getEntity
        $conteudo .= "\n$t$t" . 'public function getEntity() {' . "\n";
        $conteudo .= "$t$t$t" . 'return $this->entity;' . "\n";
        $conteudo .= "$t    }\n";

        $prepare = '';

        for ($i = 0; $i < count($objTabela->getCampos()); $i++) {
            /* Criando os atributos, setters e getters */
            if ($objTabela->getExtra($i) != 'auto_increment') {
                if ($objTabela->getCampo($i) != 'update_date' && $objTabela->getCampo($i) != 'insert_date' && $objTabela->getCampo($i) != 'ativo') {
                    $nomeCampos[] = $objTabela->getCampo($i);

                    if (in_array($objTabela->getNomeTipoCampo($i), $matInteiros)) {
                        $prepare .= "$t$t$t" . '$this->' . Util::nomeDbToAtributo($objTabela->getCampo($i)) . ' = Util::isNotEmpty($this->entity->get' . Util::nomeDbToClasse($objTabela->getCampo($i)) . '()) ? trim($this->entity->get' . Util::nomeDbToClasse($objTabela->getCampo($i)) . '()) : ' . "'" . 'NULL' . "';\n";
                    } else {
                        $data = strstr($objTabela->getCampo($i), 'data') == '' ? ('$this->entity->get' . Util::nomeDbToClasse($objTabela->getCampo($i)) . '()') : ('Util::formatDateGUIToDB($this->entity->get' . ucfirst($objTabela->getCampo($i)) . '())');
                        $prepare .= "$t$t$t" . '$this->' . Util::nomeDbToAtributo($objTabela->getCampo($i)) . ' = Util::isNotEmpty($this->entity->get' . Util::nomeDbToClasse($objTabela->getCampo($i)) . '()) ? ' . '"' . "'" . '" . ' . $data . ' . "' . "'" . '"' . ' : ' . "'" . 'NULL' . "';\n";
                    }
                    $valores[] = '$this->' . Util::nomeDbToAtributo($objTabela->getCampo($i));
                }
            }
        }

        $conteudo .= "\n$t$t" . '/**' . "\n";
        $conteudo .= "$t$t" . ' * Prepare variables to be used in sql command.' . "\n";
        $conteudo .= "$t$t" . ' */' . "\n";
        $conteudo .= "$t$t" . 'private function prepareVariables() {' . "\n";
        $conteudo .= $prepare;
        $conteudo .= "$t    }\n";
        
        //Default mysql
        $dataBanco = 'now()';

        /* Inserindo o comando para data do banco, de acordo com o banco usado, no campo data_db. */
        if (in_array('update_date', $objTabela->getCampos()) || in_array('insert_date', $objTabela->getCampos())) {
            switch ($GLOBALS['banco']) {
                case 'mssql':
                    $dataBanco = 'getdate()';
                    break;
                case 'mysql':
                    $dataBanco = 'now()';
                    break;
                case 'pq':
                    $dataBanco = '';
                    break;
                case 'oracle':
                    $dataBanco = 'sysdate';
                    break;
            }
        }

        /* Criando o m�todo inserir */
        $comentario = "\n$t$t" . '/**' . "\n$t$t" . ' * Execute the insert command on the table: ' . $objTabela->getNomeTabela() . '.' . "\n";
        $comentario .= "$t$t" . ' * @return int Number of affected rows.' . "\n$t$t */\n";

        $inserir = $comentario . "$t$t" . 'public function getInsertSQL()' . " {\n$t$t$t" . '$this->prepareVariables();' . "\n";
        $inserir .= "$t$t$t" . '$sql = ' . "'" . 'INSERT INTO ' . "'" . ' . self::TABLE_NAME . ' . "'";
        $inserir .= ' (' . implode(', ', $nomeCampos) . ', ativo, insert_date) VALUES (' . "' . " . implode(" . '" . ', ' . "' . ", $valores) . " . '" . ', \\\'S\\\', ' . $dataBanco . ')' . "'" . ';' . "\n";

        $inserir .= "$t$t$t" . 'if($this->log->isDebugEnabled()) {' . "\n";
        $inserir .= "$t$t$t$t" . '$this->log->logDebug($sql);' . "\n";
        $inserir .= "$t$t$t" . '}' . "\n";
        $inserir .= "$t$t$t" . 'return $sql;' . "\n";
        $inserir .= "$t$t}\n";

        /* Criando o metodo update */
        $comentario = "\n$t$t" . '/**' . "\n$t$t" . ' * Execute the update command on the table ' . $objTabela->getNomeTabela() . '.' . "\n";
        $comentario .= "$t$t" . ' * @return int Number of affected rows.' . "\n$t$t */\n";
        $update = $comentario . "$t$t" . 'public function getUpdateSQL()' . " {\n$t$t$t" . '$this->prepareVariables();' . "\n";
        $update .= "$t$t$t" . '$sql = ' . "'" . 'UPDATE ' . "'" . ' . self::TABLE_NAME . ' . "'" . ' SET ';
        for ($i = 0; $i < count($nomeCampos); $i++) {
            if ($nomeCampos[$i] != 'insert_date' && $nomeCampos[$i] != 'update_date') {
                $update .= ($i != 0) ? ', ' : '';
                $update .= $nomeCampos[$i] . ' = ' . "' . " . $valores[$i] . " . '";
            }
        }
        $update .= ', update_date = ' . $dataBanco . ' WHERE ID = ' . "'" . ' . $this->entity->getId()' . ";\n";

        $update .= "$t$t$t" . 'if($this->log->isDebugEnabled()) {' . "\n";
        $update .= "$t$t$t$t" . '$this->log->logDebug($sql);' . "\n";
        $update .= "$t$t$t" . '}' . "\n";
        $update .= "$t$t$t" . 'return $sql;' . "\n";
        $update .= "$t$t}\n";

        /* Criando o metodo delete */
        $delete = "\n$t$t" . '/**' . "\n$t$t" . ' * Execute the delete command on the table ' . $objTabela->getNomeTabela() . '.' . "\n";
        $delete .= "$t$t" . ' * @return int Number of affected rows.' . "\n$t$t */\n";
        $delete .= "$t$t" . 'public function getDeleteSQL()' . " {\n";
        $delete .= "$t$t$t" . 'if($this->entity->getId()) {' . "\n";
        $delete .= "$t$t$t$t" . '$sql = ' . "'" . 'DELETE FROM ' . "'" . ' . self::TABLE_NAME . ' . "'";
        $delete .= ' WHERE ID = ' . "'" . ' . $this->entity->getId();' . "\n";

        $delete .= "$t$t$t" . 'if($this->log->isDebugEnabled()) {' . "\n";
        $delete .= "$t$t$t$t" . '$this->log->logDebug($sql);' . "\n";
        $delete .= "$t$t$t" . '}' . "\n";
        $delete .= "$t$t$t$t" . 'return $sql;' . "\n";
        $delete .= "$t$t$t" . '} else {' . "\n$t$t$t$t" . '//Nothing to remove.' . "\n$t$t$t$t" . 'return 0;' . "\n";
        $delete .= "$t$t    }\n";

        $delete .= "$t    }\n";
        
        /* Criando o metodo delete lógico */
        
        
        $deleteLogico = "\n$t$t" . '/**' . "\n$t$t" . ' * Execute the logical delete command on the table categoria whitch one is just an update.
     * @return int Number of affected rows.
     */
    public function getLogicalDeleteSQL() {
        if ($this->entity->getId()) {
            $sql = \'UPDATE \' . self::TABLE_NAME . \' set ativo = null WHERE ID = \' . $this->entity->getId();
            return $sql;
        } else {
            //Nothing to remove.
            return 0;
        }
    }' . "\n";
        
        /* Creating the method find */
        $find = "\n$t$t" . '/**' . "\n$t$t" . ' * Execute the select command on the table ' . $objTabela->getNomeTabela() . '. To retrive rows.' . "\n";
        $find .= "$t$t" . ' * @param String $where' . "\n$t$t" . ' * @return Array of rows.' . "\n$t$t */\n";
        $find .= "$t$t" . 'public function getFindSQL($where = \' ativo = \'S\'\') {' . "\n";
        $find .= "$t$t$t" . '$sql = \'SELECT ';
        for ($i = 0; $i < count($objTabela->getCampos()); $i++) {
            if ($objTabela->getCampo($i) != 'ativo') {
                $find .= $i > 0 ? ', ' : '';
                $find .= $objTabela->getCampo($i);
            }
        }
        $find .= ' FROM ' . "'" . ' . self::TABLE_NAME;' . "\n";
        $find .= "$t$t$t" . 'if($where) {' . "\n";
        $find .= "$t$t$t$t" . '$sql .= \' where \' . $where;' . "\n";
        $find .= "$t$t    }\n";
        $find .= "$t$t$t" . 'if($this->log->isDebugEnabled()) {' . "\n";
        $find .= "$t$t$t$t" . '$this->log->logDebug($sql);' . "\n";
        $find .= "$t$t$t" . '}' . "\n";
        $find .= "$t$t$t" . 'return $sql;' . "\n$t    }\n";

        /* Creating the method find No Null */
        $findNN = "\n$t$t" . '/**' . "\n$t$t" . ' * Execute the select command on the table ' . $objTabela->getNomeTabela() . '. To retrive rows no null values' . "\n";
        $findNN .= "$t$t" . ' * @param String $where' . "\n$t$t" . ' * @return Array of rows.' . "\n$t$t */\n";
        $findNN .= "$t$t" . 'public function getFindNoNullSQL($where = \' ativo = \'S\'\') {' . "\n";
        $findNN .= "$t$t$t" . '$sql = \'SELECT id';
        for ($i = 0; $i < count($objTabela->getCampos()); $i++) {
            if ($objTabela->getCampo($i) != 'ativo' and $objTabela->getCampo($i) != 'id') {
                $findNN .= ', ';
                $findNN .= 'IFNULL(' . $objTabela->getCampo($i) . ", \'\') " . $objTabela->getCampo($i);
            }
        }
        $findNN .= ' FROM ' . "'" . ' . self::TABLE_NAME;' . "\n";
        $findNN .= "$t$t$t" . 'if($where) {' . "\n";
        $findNN .= "$t$t$t$t" . '$sql .= \' where \' . $where;' . "\n";
        $findNN .= "$t$t    }\n";
        $findNN .= "$t$t$t" . 'if($this->log->isDebugEnabled()) {' . "\n";
        $findNN .= "$t$t$t$t" . '$this->log->logDebug($sql);' . "\n";
        $findNN .= "$t$t$t" . '}' . "\n";
        $findNN .= "$t$t$t" . 'return $sql;' . "\n$t    }\n";
        
        
        $byEntityFindNN  = "\n$t$t" . '/**' . "\n$t$t" . ' * Execute the select command on the table ' . $objTabela->getNomeTabela() . '. To retrive rows no null values' . " Using entitys values. \n";
        $byEntityFindNN .= "$t$t" . ' */' . "\n";
        $byEntityFindNN .= "$t$t" . 'public function getByEntityFindNoNullSQL() {
            $where  = \'1 = 1\';' . "\n";
        
        //Criando o where referente a todos os atributos preenchidos.
        for ($i = 0; $i < count($objTabela->getCampos()); $i++) {
            $nomeCampo = $objTabela->getCampo($i);
            if ($nomeCampo != 'id' && $nomeCampo != 'insert_date') {
                if(strstr($objTabela->getCampo($i), 'data') == '') {
                    $byEntityFindNN .= '            $where .= Util::isNotEmpty($entity->get' . Util::nomeDbToClasse($nomeCampo) . '()) ? \' AND ' . $nomeCampo . ' = \\\'\' . trim($entity->get' . Util::nomeDbToClasse($nomeCampo) . '()) . \'\\\'\' : \'\';' . "\n";
                } else if(strstr($objTabela->getTipo($i), 'double') != '') {
                    $byEntityFindNN .= '            $where .= Util::isNotEmpty($entity->get' . Util::nomeDbToClasse($nomeCampo) . '()) ? \' AND ' . $nomeCampo . ' = \\\'\' . Util::formatNumRealGUIToDB($entity->get' . Util::nomeDbToClasse($nomeCampo) . '()) . \'\\\'\' : \'\';' . "\n";
                } else {
                    $byEntityFindNN .= '            $where .= Util::isNotEmpty($entity->get' . Util::nomeDbToClasse($nomeCampo) . '()) ? \' AND ' . $nomeCampo . ' = \\\'\' . Util::formatDateGUIToDB($entity->get' . Util::nomeDbToClasse($nomeCampo) . '()) . \'\\\'\' : \'\';' . "\n";
                }
            }
        }

        $byEntityFindNN .= '            return $this->getFindNoNullSQL($where);
        }' . "\n";

        $ultimaLinha = "    }\n?>\n";
        $conteudo .= $inserir . $update . $delete . $deleteLogico . $find . $findNN . $byEntityFindNN . $ultimaLinha;

        return $conteudo;
    }

}

?>